package com.oa.dao.impl;

import com.oa.common.base.Page;
import com.oa.common.base.Pageable;
import com.oa.common.eums.EntityStatus;
import com.oa.common.interfaces.PreFilter;
import com.oa.dao.BaseDaoImpl;
import com.oa.dao.PreFilters;
import com.oa.dao.UserDao;
import com.oa.entities.Role;
import com.oa.entities.User;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

@Repository
public class UserDaoImpl extends BaseDaoImpl<Long,User> implements UserDao {

    @Override
    protected void loadClassType() {
        setType(User.class);
    }

    @Override
    public User findByUsername(String username) {
        List<PreFilter> filters= new ArrayList<>();
        filters.add(PreFilters.or(PreFilters.eq(User.USER_USERNAME,username),
                PreFilters.eq(User.USER_EMAIL,username),
                PreFilters.eq(User.USER_PHONE,username)));
        filters.add(PreFilters.eq(User.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        PreFilter[] fs= new PreFilter[filters.size()];
        return findUnqiue(filters.toArray(fs));
    }

    @Override
    public Page<User> findPage(Pageable pageable, String key) {
        StringBuilder builder= new StringBuilder();
        builder.append("select user from User user ");
        if (!StringUtils.isEmpty(key)){
            builder.append("join user.info info,info.department department ");
        }
        builder.append(" where user.status=:status and user.manager= :manage");
        if(!StringUtils.isEmpty(key)){
            builder.append(" and(user.username like :key or user.phone like :key or user.email like : key");
            builder.append(" or info.nickName like :key or department.name like :key)");
        }
        Query query= getSession().createQuery(builder.toString()).setFirstResult((pageable.getPageNumber()-1)
                *pageable.getPageSize()).setMaxResults(pageable.getPageSize())
                .setParameter("status",EntityStatus.ENTITY_EABLE.getCode())
                .setParameter("manage",false);
        if (!StringUtils.isEmpty(key)){
            key="%"+key+"%";
            query.setParameter("key",key);
        }
        List<User> users= query.list();
        Criteria criteria= getCriteria();
        criteria.add(Restrictions. eq(User.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        criteria.add(Restrictions.eq("manager",false));
        if (!StringUtils.isEmpty(key)){
            key="%"+key+"%";
            criteria.createAlias("info","info");
            criteria.createAlias("info.department","department");
            criteria.add(Restrictions.or(Restrictions.like("username",key),
                    Restrictions.like("phone",key),
                    Restrictions.like("email",key),
                    Restrictions.like("info.nickName",key),
                    Restrictions.like("department",key)));
        }
        long count= (long) criteria.setProjection(Projections.rowCount()).uniqueResult();
        return new Page<>(pageable,users,new Long(count).intValue());
    }

    @Override
    public Boolean validateByDepartment(Long departmentId) {
        StringBuilder builder= new StringBuilder();
        builder.append("select user from User user join user.info.department as department where ");
        builder.append("department.id= :departmentId and user.status= :status");
        List<User> users= getSession().createQuery(builder.toString()).setParameter("departmentId",departmentId)
                .setParameter("status",EntityStatus.ENTITY_EABLE.getCode()).list();
        return users!=null && users.size()>0;
    }

    @Override
    public Boolean validateByRole(Long roleId) {
        StringBuilder builder= new StringBuilder();
        builder.append("select user from User user join user.roles as roles");
        builder.append(" where roles.id=:roleId and status= :status");
        List<Role> roles= getSession().createQuery(builder.toString()).setParameter("roleId",roleId)
                .setParameter("status",EntityStatus.ENTITY_EABLE.getCode()).list();
        return roles!=null && roles.size()>0;
    }

    @Override
    public Boolean validateUsername(String username,Long id) {
        List<PreFilter> filters= new ArrayList<>();
        filters.add(PreFilters.eq(User.USER_USERNAME,username));
        filters.add(PreFilters.eq(User.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        if (id!=null){
            filters.add(PreFilters.eq(User.PROP_ID,id));
        }
        PreFilter[] fs= new PreFilter[filters.size()];
        return findUnqiue(filters.toArray(fs))!=null;
    }

    @Override
    public Boolean validatePhone(String phone, Long id) {
        List<PreFilter> filters= new ArrayList<>();
        filters.add(PreFilters.eq(User.USER_PHONE,phone));
        filters.add(PreFilters.eq(User.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        if (id!=null){
            filters.add(PreFilters.eq(User.PROP_ID,id));
        }
        PreFilter[] fs= new PreFilter[filters.size()];
        return findUnqiue(filters.toArray(fs))!=null;
    }

    @Override
    public Boolean validateEmail(String email, Long id) {
        List<PreFilter> filters= new ArrayList<>();
        filters.add(PreFilters.eq(User.USER_EMAIL,email));
        filters.add(PreFilters.eq(User.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        if (id!=null){
            filters.add(PreFilters.eq(User.PROP_ID,id));
        }
        PreFilter[] fs= new PreFilter[filters.size()];
        return findUnqiue(filters.toArray(fs))!=null;
    }
}
